package com.cash.app.utils

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.util.Base64
import com.cash.app.constant.AppConstant.IMAGE_BASE_64
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.ByteArrayOutputStream
import java.io.IOException

object ImageBase64Utils {

    private const val TAG = "ImageBase64Utils"
    private const val MAX_FILE_SIZE = 500 * 1024 // 500KB in bytes
    private const val INITIAL_QUALITY = 80
    private const val MIN_QUALITY = 20
    private const val QUALITY_STEP = 20
    private const val SCALE_STEP = 0.8f
    private const val MIN_SCALE = 0.1f

    suspend fun convertImagesToBase64(context: Context, uris: List<Uri>): List<String> =
        withContext(Dispatchers.IO) {
            uris.mapNotNull { uri ->
                try {
                    convertImageToBase64(context, uri)
                } catch (e: IOException) {
                    TLog.e("Convert failed: ${e.message}", TAG)
                    null
                }
            }
        }

    private fun convertImageToBase64(context: Context, uri: Uri): String {
        val fileSize = context.contentResolver.openInputStream(uri)?.use {
            it.available().toLong()
        } ?: throw IOException("Failed to get file size")

        TLog.d("Original file size: $fileSize bytes", TAG)
        if (fileSize <= MAX_FILE_SIZE) {
            return context.contentResolver.openInputStream(uri)?.use { inputStream ->
                val bytes = inputStream.readBytes()
                IMAGE_BASE_64.plus(Base64.encodeToString(bytes, Base64.NO_WRAP))
            } ?: throw IOException("Failed to read input stream")
        }

        TLog.d("File size exceeds limit, starting compression", TAG)
        var bitmap = context.contentResolver.openInputStream(uri)?.use {
            BitmapFactory.decodeStream(it)
        } ?: throw IOException("Failed to decode bitmap")

        var quality = INITIAL_QUALITY
        var compressedBytes: ByteArray
        var scale = 1.0f
        var shouldContinue = true

        do {
            val outputStream = ByteArrayOutputStream()
            bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream)
            compressedBytes = outputStream.toByteArray()
            outputStream.close()

            if (compressedBytes.size > MAX_FILE_SIZE) {
                if (quality > MIN_QUALITY) {
                    quality -= QUALITY_STEP
                } else if (scale > MIN_SCALE) {
                    val oldBitmap = bitmap
                    scale *= SCALE_STEP
                    bitmap = scaleBitmap(oldBitmap, scale)
                    oldBitmap.recycle()
                    quality = INITIAL_QUALITY
                } else {
                    shouldContinue = false
                }
            } else {
                shouldContinue = false
            }
        } while (shouldContinue)

        bitmap.recycle()
        TLog.i("Final: q=$quality s=$scale size=${compressedBytes.size / 1024}KB", TAG)
        return IMAGE_BASE_64.plus(Base64.encodeToString(compressedBytes, Base64.NO_WRAP))
    }

    private fun scaleBitmap(bitmap: Bitmap, scale: Float): Bitmap {
        val width = (bitmap.width * scale).toInt().coerceAtLeast(1)
        val height = (bitmap.height * scale).toInt().coerceAtLeast(1)
        return Bitmap.createScaledBitmap(bitmap, width, height, true)
    }
} 